#!/usr/bin/env bash

# UTILITY FUNCTIONS {{{
# ===
_hr="------------"

# Dump to the screen in a formatted way
# ---
#
# _headline string - First argument, printed above horizontal rule
# $@        string - Remaining arguments, printed below horizontal rule
puts() {
  local _headline="$1"
  shift
  local _arr="$@"
  local _i=1
  shift
  printf "\n  %s:\n  %s\n" "$_headline" "$_hr"
  for _x in ${_arr[@]}; do
    printf "    %s. %s\n" "$_i" "$_x"
    (( i++ ))
  done
  unset _headline _i _x _arr
}

restart_trayer() {
  starttrayer
}
# --------------------------------------------------------------------- }}}

# XRANDR FUNCTIONS {{{
# =====

_local_displays=("LVDS" "eDP1")
_external_displays=("HDMI" "VGA" "DVI" "DP1")

# Cache output of xrandr -q
# ---
#
# refresh mixed - whether or not to refresh.
#                 Any arugment is true here
get_xrandr() {
  (( "$#" > 0 )) && xrandr=
  [[ -z "$xrandr" ]] && xrandr=$(xrandr -q)
}

get_all() {
  get_xrandr
  xrandr_all=( $(echo "$xrandr" | awk '/connected/ {print $1}' | sort) )
}

# Find connected ouputs
get_connected() {
  get_xrandr
  [[ -z "$xrandr_connected" ]] && \
  xrandr_connected=( $(echo "$xrandr" | awk '/ connected/ {print $1}' | sort) )
}

get_disconnected() {
  get_xrandr
  xrandr_disconnected=( $(echo "$xrandr" | awk '/disconnected/ {print $1}' | sort) )
}

# Find local, connected output
get_local() {
  get_connected
  for _local_display in "${_local_displays[@]}"; do
    for _conn_display in "${xrandr_connected[@]}"; do
      if [[ "$_conn_display" == $_local_display* ]]; then
        xrandr_local="$_conn_display"
        break
      fi
    done
  done
}

# Find primary external, connected output
get_external() {
  get_connected
  for _ext_display in "${_external_displays[@]}"; do
    for _conn_display in "${xrandr_connected[@]}"; do
      if [[ "$_conn_display" =~ $_ext_display* ]]; then
        xrandr_external="$_conn_display"
        break
      fi
    done
  done
}

mirror() {
  get_local
  get_external

  local _primary="${xrandr_local[0]}"
  local _secondary="${xrandr_external[0]}"
  local -A _native_resolution
  local _auto="--auto"

  # Override navive resolution for high-dpi laptops. Looking at you ASUS Zenbook
  if [[ -r "$HOME/.monitorfix" ]]; then
    _auto=""
    local _override_display=$(grep ^display= "$HOME/.monitorfix" | cut -d= -f2)
    _native_resolution[$_override_display]=$(grep ^native_resolution= "$HOME/.monitorfix" | cut -d= -f2)
  fi

  # require external display
  [[ -z "$xrandr_external" ]] && exit 1

  while read _line; do
    if [[ "$_line" == Screen* ]]; then
      continue
    fi

    if [[ "$_line" == [A-Z]* ]]; then
      set -- $_line
      local _source="$1"
    else
      if [[ -z "${_native_resolution[$_source]}" ]]; then
        set -- $_line
        _native_resolution[$_source]="$(echo "$1" \
          | sed "s/\([[:digit:]]*x[[:digit:]]*\)\?.*/\1/")"
      fi
    fi
  done < <(xrandr -q)

  set -- $(echo ${_native_resolution[$_primary]} | tr "x" " ")
  local _primary_x="$1"
  local _primary_y="$2"

  set -- $(echo ${_native_resolution[$_secondary]} | tr "x" " ")
  local _secondary_x="$1"
  local _secondary_y="$2"

  local _x_scaling=$(echo "scale=4;$_primary_x/$_secondary_x" | bc)
  local _y_scaling=$(echo "scale=4;$_primary_y/$_secondary_y" | bc)

  local _sec="--output $_secondary --scale ${_x_scaling}x${_y_scaling} --auto"
  local _pri="--output $_primary --same-as ${_secondary} --scale 1x1 --primary ${_auto}"
  xrandr $_sec $_pri
}

nightmode() {
  get_local

  echo "$1"
  case $1 in
    on|On|ON|oN)
      xrandr --output "$xrandr_local" --gamma 1.68215:1:0.62 --brightness 0.75
      ;;
    of*|oF*|OF*|Of*)
      xrandr --output "$xrandr_local" --gamma 0.97:1:0.98 --brightness 0.98
      ;;
    *)
      show_help
      ;;
  esac
}

# Ben Wong,  October 1, 2010
# Public domain.  No rights reserved.
# Functionality extended by Chris Lockfort, August 23, 2012 for use in X230 tablets running gnome-shell.
tablet() {
  get_local

  rot="$1"

  if [[ -z "$rot" ]]; then
        rot=$(xrandr -q | \
            awk -v display="$xrandr_local" \
                '$0 ~ display {
                    gsub("[()]", "")
                    gsub("primary ", "")
                    print $4
                }')
        echo "The rot is $rot"
    # rot=$(xrandr -q | grep "$xrandr_local" | awk '{print $4}' | tr -d '(')
  fi

  case $rot in
    left) # Currently top is rotated left, we should set it normal (0°)
      xrandr --output "$xrandr_local" --rotate normal
      for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
        xsetwacom set $_device Rotate none;
      done
      ;;
    normal)  # Screen is not rotated, we should rotate it right (90°)
      xrandr --output "$xrandr_local" --rotate right
      for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
        xsetwacom set $_device Rotate cw;
      done
      ;;
    right)    # Top of screen is rotated right, we should invert it (180°)
      xrandr --output "$xrandr_local" --rotate inverted
      for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
        xsetwacom set $_device Rotate half;
      done
      ;;
    inverted)  # Screen is inverted, we should rotate it left (270°)
      xrandr --output "$xrandr_local" --rotate left
      for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
        xsetwacom set $_device Rotate ccw;
      done
      ;;
  esac

  # restart_trayer
}

# --------------------------------------------------------------------- }}}

# OUTPUT FUNCTIONS {{{
# ===

# help function, obvs
show_help() {
  cat <<HELP
    Usage:
        $0 [COMMAND]...

    COMMANDS:
                 all   show all connected and disconnected displays
           connected   show connected displays
        disconnected   show disconnected displays
               local   show local connected displays
            external   show external connected displays
              mirror   mirror local display with first connected display
  nightmode <on|off>   modifys the gamma and brightness to approximate xflux

    Example:
        $0 disconnected

HELP
}

show_all() {
  get_all
  puts "All Available Displays" "${xrandr_all[@]}"
}

show_connected() {
  get_connected
  puts "Connected Displays" "${xrandr_connected[@]}"
}

show_disconnected() {
  get_disconnected
  puts "Connected Displays" "${xrandr_disconnected[@]}"
}

show_local() {
  get_local
  puts "Local Connected Display" "${xrandr_local[@]}"
}

show_external() {
  get_external
  puts "External Connected Displays" "${xrandr_external[@]}"
}
# --------------------------------------------------------------------- }}}

# MAIN EVENT LOOP {{{
# ===
main() {
  local _tabletfile="/tmp/tabletmode"

  case $1 in
    all) show_all ;;
    connected) show_connected ;;
    disconnected) show_disconnected ;;
    local) show_local ;;
    external) show_external ;;
    mirror) mirror ;;
    tablet) tablet ;;
    unfuck)
        notify-send "Attempting to unfuck the display"
        tablet "left" && sleep 2
        tablet "right" && sleep 2
        tablet "left" && sleep 2
        tablet "right" && sleep 2
        tablet "normal"
        ;;
    tabletmode)
      touch $_tabletfile
      if [[ "$(cat $_tabletfile)" == "on" ]]; then
        printf "off" > $_tabletfile
        notify-send "Laptop Mode"
        tablet "left"
        killall cellwriter
      else
        if command -v 'cellwriter' &> /dev/null; then
          cellwriter --window-x=15 --window-y=100 &
        fi
        printf "on" > $_tabletfile
        notify-send "Tablet Mode"
        tablet "right"
      fi
      ;;
    nightmode)
      shift
      nightmode "$1"
    ;;
    *) show_help ;;
  esac
}
# --------------------------------------------------------------------- }}}

main "$@"
